<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title>music-jmgraph</title>
<style>
	html,body{
		color: #9DA0AD;
		background-color: #272822;
        overflow: hidden;
	}
</style>
</head>
<body>
<div style="border-radius: 10px; border: 1px solid #ccc; box-shadow: #fff 0 0 10px; background-color: rgba(255,255,255,0.2); color:#000; width: 400px; height: 200px; position: fixed; top: 40%; left: 40%">
    <span>请选择音频文件</span> <br />
    <input type="file" id="my_sound" /> <br />
    <input type="checkbox" id="chk_loop" checked="true" /> <span>循环播放</span><br />
    <button id="btn_play">播放</button> <br />
    <span id="txtstatus"></span><br />
</div>
<canvas id="sound_canvas"></canvas>
<script type="module">
	import jmGraph from "../index.js";
	(function(){
		//初始化jmgraph
        var graph = new jmGraph('sound_canvas', {
            mode: 'webgl',
            width: window.innerWidth,
		    height: window.innerHeight * 0.95,
        });

		window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
		//动画用到
        window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame;

		if(typeof window.AudioContext == 'undefined') {
			alert('不支持');
			return;
		}
		var audioContext = null;
		//音频容器
		var audioBufferSouceNode, analyser, currentAudioData = null;	

		//读取音频文件
		window.readSound = function(file) {
			var fr = new FileReader();
			fr.onload = function(e) {
				//解码文件
				decodeAudio(e.target.result);
                //currentAudioData = e.target.result;
			}
			fr.readAsArrayBuffer(file);
		}

		//解码
		function decodeAudio(data) {
            if(!audioContext) {
                audioContext = new window.AudioContext();
                audioContext.onstatechange = function(e) {
                    console.log(e);
                }
            }

            currentAudioData = data.slice(0);

				log('解码中...');
			audioContext.decodeAudioData(data, function(buffer){
				log('解码成功');
				play(buffer); //播放
			}, function(e){
				log('解码失败,' + e.message);
			});
		}

		//播放
		function play(buffer) {		
			//如果 已在播放，则中止
			if(audioBufferSouceNode) {
				audioBufferSouceNode.stop();
			}
            //AudioBufferSourceNode 
			audioBufferSouceNode = audioContext.createBufferSource();	
			audioBufferSouceNode.buffer = buffer;
            audioBufferSouceNode.loop = document.getElementById('chk_loop').checked; // 循环

            audioBufferSouceNode.onended = function(e) {
                log('播放结束', e);
            }
			////连接到扬声器
			//audioBufferSouceNode.connect(audioContext.destination);
			//处理频谱
			createAnalyser(audioBufferSouceNode);
			//开始播放
			audioBufferSouceNode.start(0);
            log('播放中');
		}

		//生成频谱分析
		function createAnalyser(souceNode) {
			if(analyser) {				
				analyser.disconnect(audioContext.destination);
			}
			//频谱能量分析器
			analyser = audioContext.createAnalyser();
			souceNode.connect(analyser);
            
			//扬声器
			analyser.connect(audioContext.destination);
		}

		//画频谱能量图
		function drawAnalyserData() {
            if(analyser) {
                //获取频率能量值
                var array = new Uint8Array(analyser.frequencyBinCount);
                analyser.getByteFrequencyData(array);
                var arrper = 10;
                var count = Math.floor(array.length / arrper);
                //每个柱子的宽度
                var w = graph.width / count;

                var perh = graph.height / 300;

                for(var i=0;i<count; i++) {
                    var start = i*arrper;
                    var end = start + arrper;
                    var arr = array.slice(start, end);
                    var sum = 0;
                    arr.forEach(p=>sum+=p);

                    var h = perh * sum/arr.length;
                    var bar = graph.children.get(i);
                    var y = graph.height - h;

                    if(!bar)  {
                        var x = i * (w + 4);
                        bar = graph.createShape('rect', {
                            position: {
                                x, y
                            },
                            width: w,
                            height: h,
                            style: {
                                //stroke: '#cccccc',
                                // linear-gradient(x1 y1 x2 y2, color1 step, color2 step, ...)
                                fill: '#B2F70D'//'linear-gradient(0 0 0 100%, #0D8E21 1, #B2F70D 0.5, #D6FA03 0)'
                            }
                        });
                        graph.children.add(bar);
                    }
                    else {
                        bar.height = h;
                    }
                    bar.position.y = y;
                }

                graph.redraw();
            }
            window.requestAnimationFrame(drawAnalyserData);
		}

		bindEvent();

        drawAnalyserData(analyser);//绘制漂亮的频谱图

		log('加载中mp3...');
		loadSoundFile('data/ringing_short.mp3', function(buffer) {
			//decodeAudio(buffer);
            currentAudioData = buffer;
            log('加载完成');
		});

        function bindEvent() {
            //选择文件
            document.getElementById('my_sound').onchange = function(e) {
                if(this.files.length) {
                    var file = this.files[0];
                    window.readSound(file);
                }
            }
            document.getElementById('btn_play').onclick = function(e) {
                if(currentAudioData) {
                    decodeAudio(currentAudioData);
                }
            }
        }
	})();


	//获取远程音频文件
	function loadSoundFile(url,callback) {
	    var request = new XMLHttpRequest(); 
	    request.open('GET', url, true); 
	    request.responseType = 'arraybuffer'; 
	    //音频获取
	    request.onload = function() {
	        var arraybuffer = request.response;
	        callback && callback(arraybuffer);
	    }
	    request.send();
	}

	function log(msg) {
		document.getElementById('txtstatus').innerHTML = msg;
        console.log(...arguments);
	}
</script>
</body>
</html>